const util = require('util');
const debug = util.debuglog('oil-game:upgrade:cache');
const BigNumber = require("bignumber.js");

const {
    updateUpgrade,    // 保存用户升级信息
    getUpgradeByMongo,    //从Mongo中查询用户升级信息
} = require('./dao');
const {
    LOGOUT_COINS_PREFIX,    //离线奖励前缀
    ADD_INCOMERATE_PREFIX,    //采集收入加速前缀
} = require('./consts');
const {
    RedisPrefix
} = require('../../../util/consts');

//查看内存中User的升级信息
exports.getUpgradeData = async function (uid) {
    debug("用户 %s 获取User升级信息", uid);
    let user = await this.app.userRemote(uid, 'get', [uid, 'user']);
    if (!user) {
        debug("用户 %s 获取User升级信息，内存中没有此用户，返回null", uid);
        return null;
    }
    if (user.upgrade) {
        debug("用户 %s 获取User升级信息，内存中查找到该数据，直接返回 %s", uid, JSON.stringify(user.upgrade));
        //从内存中获取的金币转换为BigNumber
        user.upgrade.coins = new BigNumber(user.upgrade.coins);
        return user.upgrade;
    }
    //如果内存中不存在该数据，则从数据库中查询
    let upgrade = await getUpgradeByMongo(uid);
    //将等级信息挂载到user内存中
    if (upgrade) {
        debug("用户 s% 获取User升级信息，从数据库获取到升级信息，开始挂载到user中 %s", uid, JSON.stringify(upgrade));
        //从数据库获取的金币转换为BigNumber
        upgrade.coins = new BigNumber(upgrade.coins);
        if (upgrade.coins.isNaN()) {
            debug("uid = %s upgrade.coins = %s 从数据库获取的金币数非法，coins为NaN", uid, upgrade.coins.toString());
            upgrade.coins = new BigNumber(0);
        }
        await this.app.userRemote(uid, "set", [uid, "user.upgrade", upgrade]);
    }
    //返回从数据库查询的数据
    return upgrade;
};

//设置内存中的上次更新时间
exports.setLastUpdateCoins = async function (uid, nowDate) {
    debug("uid = %s  nowDate = %s  设置上次更新时间", uid, nowDate);
    await exports.getUpgradeData.call(this, uid);
    //更新上次更新金币时间
    await this.app.userRemote(uid, "set", [uid, "user.upgrade.last_update_coins", nowDate]);
}

//设置内存中upgrade的当前金币数量并修改上次更新时间
exports.setUpgradeCoins = async function (uid, coins, nowDate) {
    debug("uid = %s  coins = %s  nowDate = %s  更新当前金币数量和时间", uid, coins, nowDate);
    if (coins.isNaN()) {
        debug("uid = %s 更新当前金币数量非法，coins为NaN", uid);
        return;
    }
    coins = coins.toFormat(0);
    coins = "" + coins.replace(/[,]/ig, "");
    //更新金币数量
    await this.app.userRemote(uid, "set", [uid, "user.upgrade.coins", coins]);
    //更新上次更新金币时间
    await this.app.userRemote(uid, "set", [uid, "user.upgrade.last_update_coins", nowDate]);
}

//深度升级
exports.incrUpgradeDepth_level = async function (uid) {
    debug("uid = %s  深度升一级", uid);
    await this.app.userRemote(uid, "com", [uid, "user.upgrade.depth_level++;"]);
}

//品质升级
exports.incrUpgradeQuality_level = async function (uid) {
    debug("uid = %s  品质升一级", uid);
    await this.app.userRemote(uid, "com", [uid, "user.upgrade.quality_level++;"]);
}

//速度升级
exports.incrUpgradeSpreed_level = async function (uid) {
    debug("uid = %s  速度升一级", uid);
    await this.app.userRemote(uid, "com", [uid, "user.upgrade.spreed_level++;"]);
}

//扣除金币数量，coins为BigNumber
exports.reduceCoins = async function (uid, coins) {
    debug("uid = %s  coins = %s  扣除金币数量", uid, coins.toString());
    let upgrade = await exports.getUpgradeData.call(this, uid);
    let oldCoins = new BigNumber(upgrade.coins);
    let newCoins = oldCoins.minus(coins);
    if (newCoins.isNaN()) {
        debug("uid = %s oldCoins = %s 扣除金币数量非法，coins为NaN", uid, oldCoins.toString());
        return;
    }
    newCoins = newCoins.toFormat(0);
    newCoins = "" + newCoins.replace(/[,]/ig, "");
    await this.app.userRemote(uid, "com", [uid, "user.upgrade.coins=" + newCoins]);
}

//增加金币数量
exports.addCoins = async function (uid, coins) {
    debug("uid = %s  增加金币数量 = ", uid, coins);
    let upgrade = await exports.getUpgradeData.call(this, uid);
    let oldCoins = new BigNumber(upgrade.coins);
    let subCoins = new BigNumber(coins);
    let newCoins = oldCoins.plus(subCoins);
    if (newCoins.isNaN()) {
        debug("uid = %s oldCoins = %s 扣除金币数量非法，coins为NaN", uid, oldCoins.toString());
        return;
    }
    newCoins = newCoins.toFormat(0);
    newCoins = "" + newCoins.replace(/[,]/ig, "");
    await this.app.userRemote(uid, "com", [uid, "user.upgrade.coins=" + newCoins]);
}

//同步内存中的升级信息到数据库
exports.syncUpgrade = async function (upgrade) {
    debug("同步内存中的升级信息数据表 %s", JSON.stringify(upgrade));
    // 同步内存中的升级信息到数据库
    await updateUpgrade(upgrade);
}

//存储离线金币到缓存中
exports.saveLogoutCoins = function (uid, logOutCoins) {
    debug("uid = %s  logOutCoins = %s  存储离线金币到缓存中", uid, logOutCoins);
    let redis = this.app.get('redis');
    let key = LOGOUT_COINS_PREFIX + uid;
    logOutCoins = logOutCoins.toFormat(0);
    logOutCoins = "" + logOutCoins.replace(/[,]/ig, "");

    return new Promise((resolve, reject) => {
        redis.set(key, logOutCoins, function (err, data) {
            if (err) {
                debug("uid = %s 存储离线金币到缓存中异常  %s", uid, JSON.stringify(err));
                return reject(err);
            }
            debug("uid = %s 存储离线金币到缓存中成功  %s", uid, JSON.stringify(data));
            resolve(data);
        });
    });
}

//从缓存中获取离线金币
exports.getLogoutCoins = function (uid) {
    debug("uid = %s  从缓存中获取离线金币", uid);
    let redis = this.app.get('redis');
    let key = LOGOUT_COINS_PREFIX + uid;

    return new Promise((resolve, reject) => {
        redis.get(key, function (err, data) {
            if (err) {
                debug("uid = %s  从缓存中获取离线金币异常  %s", uid, JSON.stringify(err));
                return reject(err);
            }
            redis.del(key, function (err, data1) {
                if (err) {
                    debug("uid = %s  从缓存中获取离线金币后删除键异常  %s", uid, JSON.stringify(err));
                    return reject(err);
                }
                debug("uid = %s 从缓存中获取离线金币并删除键成功  %s", uid, JSON.stringify(data));
                resolve(data ? new BigNumber(data) : new BigNumber(0));
            });
        });
    });
}

//获取当前用户上线时间
exports.getLastLoginTime = async function (uid) {
    debug("用户 %s 获取当前用户上线时间", uid);
    let user = await this.app.userRemote(uid, 'get', [uid, 'user']);
    if (!user) {
        debug("用户 %s 获取当前用户上线时间，内存中没有此用户，返回null", uid);
        return null;
    }
    return await this.app.userRemote(uid, 'get', [uid, 'user.last_login_time']);
}

//设置采集收入加速
exports.setIncomeRate = async function (uid, time) {
    debug("uid = %s  time = %s  设置采集收入加速", uid, time);
    let redis = this.app.get('redis');
    let key = ADD_INCOMERATE_PREFIX + uid;

    return new Promise((resolve, reject) => {
        redis.set(key, "", function (err, data) {
            if (err) {
                debug("uid = %s  设置采集收入加速异常  %s", uid, JSON.stringify(err));
                return reject(err);
            }
            redis.expire(key, time, function (err, data1) {
                if (err) {
                    debug("uid = %s  设置采集收入加速异常  %s", uid, JSON.stringify(err));
                    return reject(err);
                }
                debug("uid = %s 设置采集收入加速成功  %s", uid, JSON.stringify(data));
                resolve(data);
            });
        });
    });
}

//获取是否采集收入加速
exports.isIncomeRate = async function (uid) {
    debug("uid = %s  获取是否采集收入加速", uid);
    let redis = this.app.get('redis');
    let key = ADD_INCOMERATE_PREFIX + uid;

    return new Promise((resolve, reject) => {
        redis.exists(key, function (err, data) {
            if (err) {
                debug("uid = %s  获取是否采集收入加速异常  %s", uid, JSON.stringify(err));
                return reject(err);
            }
            resolve(!!data);
        });
    });
}

//判断双倍奖励是否开启
exports.doubleRewardExists = async function (uid) {
    let redis = this.app.get('redis');
    let key = RedisPrefix.DOUBLE_REWARD + uid + '@' + RedisPrefix.DOUBLE_REWARD_END;

    return new Promise((resolve, reject) => {
        redis.exists(key, function (err, data) {
            if (err) {
                return reject(err);
            }
            resolve(data == 1);
        });
    });
}

//开启双倍奖励
exports.openDouble =  function (uid, ttl) {
    let redis = this.app.get('redis');
    let key = RedisPrefix.DOUBLE_REWARD + uid + '@' + RedisPrefix.DOUBLE_REWARD_END;
    return new Promise((resolve, reject) => {
        redis.exists(key, function (err, data) {
            if (err) return reject(err);
            //如果双倍奖励已经存在
            if (data == 1) {
                redis.ttl(key, function (err, data) {
                    if (err) return reject(err);
                    //在当前的剩余时间上，继续附加时间
                    redis.expire(key, Number(ttl) + Number(data), function (err, data) {
                        if (err) return reject(err);
                        resolve();
                    });
                })
            } else {
                redis.set(key, true, function (err, data) {
                    if (err) return reject(err);
                    redis.expire(key, ttl, function(err, data) {
                        if (err) return reject(err);
                        resolve();
                    });
                });
            }
        });
    });
}
